package com.xxx.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xxx.common.base.constants.RedisKey;
import com.xxx.common.redis.service.RedisService;
import com.xxx.user.dao.mapper.MenuMapper;
import com.xxx.user.dao.mapper.RoleMenuMapper;
import com.xxx.user.domain.entity.MenuDO;
import com.xxx.user.domain.entity.RoleMenuDO;
import com.xxx.user.dto.MenuCreateReqDTO;
import com.xxx.user.dto.MenuGetAllResDTO;
import com.xxx.user.dto.MenuUpdateReqDTO;
import com.xxx.user.service.MenuService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
@AllArgsConstructor
public class MenuServiceImpl implements MenuService {

    private final MenuMapper menuMapper;
    private final RoleMenuMapper roleMenuMapper;
    private final RedisService redisService;

    @Override
    public String create(MenuCreateReqDTO param) {
        MenuDO menuDO = new MenuDO();
        BeanUtil.copyProperties(param, menuDO);
        menuMapper.insert(menuDO);
        return "创建成功！";
    }

    @Override
    public String update(MenuUpdateReqDTO param) {
        MenuDO menuDO = new MenuDO();
        BeanUtil.copyProperties(param, menuDO);
        menuMapper.updateById(menuDO);
        return "更新成功！";
    }

    @Override
    public String delete(List<Long> ids) {
        menuMapper.deleteBatchIds(ids);
        return "删除成功！";
    }

    @Override
    public List<MenuGetAllResDTO> getAll() {

        List<MenuDO> menuDOS = menuMapper.selectList(null);

        List<MenuGetAllResDTO> roleGetAllResDTOS = menuDOS.stream()
                .map(it -> {
                    MenuGetAllResDTO resDTO = new MenuGetAllResDTO();
                    BeanUtil.copyProperties(it, resDTO);
                    return resDTO;
                })
                .sorted(Comparator.comparing(MenuGetAllResDTO::getOrderNum))
                .toList();

        return buildTree(roleGetAllResDTOS);
    }


    public Boolean refreshMenuCache(List<Long> menuIds) {

        LambdaQueryWrapper<MenuDO> queryWrapper = new LambdaQueryWrapper<MenuDO>()
                .in(CollectionUtils.isEmpty(menuIds), MenuDO::getId, menuIds);
        List<MenuDO> menuDOS = menuMapper.selectList(queryWrapper);
        Assert.notNull(menuDOS, "菜单不存在");

        for (MenuDO menuDO : menuDOS) {
            //获取该菜单允许的角色id
            List<RoleMenuDO> roleMenuDOS = roleMenuMapper.selectList(new LambdaQueryWrapper<RoleMenuDO>()
                    .eq(RoleMenuDO::getMenuId, menuDO.getId()));
            redisService.setCacheMapValue(RedisKey.ROLE_MENU_MAP, menuDO.getComponent(), roleMenuDOS.stream().map(RoleMenuDO::getRoleId).collect(Collectors.toSet()));
        }

        return Boolean.TRUE;
    }


    /*** list 转树形结构 */
    private List<MenuGetAllResDTO> buildTree(List<MenuGetAllResDTO> list) {
        // 创建一个Map，以id为键，MenuGetAllResDTO对象为值
        Map<Long, MenuGetAllResDTO> map = list.stream()
                .collect(Collectors.toMap(MenuGetAllResDTO::getId, item -> item));

        // 递归构建树
        return buildTreeRecursive(map, 0L);
    }

    /*** list 转树形结构 */
    private List<MenuGetAllResDTO> buildTreeRecursive(Map<Long, MenuGetAllResDTO> map, Long parentId) {
        List<MenuGetAllResDTO> tree = new LinkedList<>();
        for (Map.Entry<Long, MenuGetAllResDTO> entry : map.entrySet()) {
            MenuGetAllResDTO item = entry.getValue();
            if (parentId.equals(item.getParentId())) {
                List<MenuGetAllResDTO> children = buildTreeRecursive(map, item.getId());
                item.setChildren(children);
                tree.addFirst(item);
            }
        }
        return tree;
    }
}
